package com.ssm.basis.web.util;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ssm.basis.model.pojo.Result;
import com.ssm.basis.service.exception.CustomException;
import com.ssm.basis.service.util.SsmContextHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.MediaTypeFactory;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.StreamUtils;

import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URLEncoder;
import java.util.Locale;

import static com.ssm.basis.model.pojo.Result.OK_REASON_PHRASE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Objects.nonNull;

public abstract class ResponseUtil {
    static ObjectMapper objectMapper;

    public static void responseWrite(ServletResponse response, Object body) {
        response.setLocale(Locale.CHINA);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(UTF_8.name());

        try (PrintWriter writer = response.getWriter()) {
            if (body instanceof Result) {
                writer.write(objectMapper.writeValueAsString(body));
            } else {
                String message = nonNull(SsmContextHolder.getMessage()) ? SsmContextHolder.getMessage() : OK_REASON_PHRASE;
                writer.write(objectMapper.writeValueAsString(Result.ok(body).setMessage(message)));
            }
        } catch (IOException e) {
            throw new CustomException(e);
        }
    }

    /**
     * @param filename 带后缀
     * @see MimeTypeUtils
     */
    public static void download(HttpServletResponse response, String filename, byte[] bytes) {
        response.setLocale(Locale.CHINA);
        // https://blog.csdn.net/u012881904/article/details/104590720
        MediaType mediaType = MediaTypeFactory.getMediaType(filename).orElse(MediaType.APPLICATION_OCTET_STREAM);
        response.setContentType(mediaType.toString());
        response.setCharacterEncoding(UTF_8.name());

        try (ServletOutputStream outputStream = response.getOutputStream()) {
            response.setHeader(HttpHeaders.CONTENT_DISPOSITION, downloadNameEncode(filename));
            StreamUtils.copy(bytes, outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static String downloadNameEncode(String fileName) {
        // HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        // String header = request.getHeader(HttpHeaders.USER_AGENT).toUpperCase();

        try { // RFC 6266 https://www.cnblogs.com/zhengxl5566/p/13492602.html
            // 对真实文件名进行百分号编码
            String percentEncodedFileName = URLEncoder.encode(fileName, UTF_8.name()).replaceAll("\\+", "%20");
            // 组装 contentDisposition 的值
            StringBuilder contentDispositionValue = new StringBuilder();
            contentDispositionValue.append("attachment; filename=")
                    .append(percentEncodedFileName)
                    .append(";")
                    .append("filename*=")
                    .append("utf-8''")
                    .append(percentEncodedFileName);
            return contentDispositionValue.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "attachment; filename=" + fileName + ";target=_blank";
    }

    @Autowired
    void setObjectMapper(ObjectMapper objectMapper) {
        ResponseUtil.objectMapper = objectMapper;
    }
}